﻿namespace Pagination
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reactive.Linq;
    using System.Text;
    using System.Windows;
    using Microsoft.Phone.Controls;
    using Models;
    using WP7Contrib.Collections;

    public partial class MainPage : PhoneApplicationPage
    {
        private readonly IList<Employee> _allEmployees;
        private readonly PagedListView<Employee> _employees;
        private Employee _currentEmployee;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            _allEmployees = CreateEmployees(10023);
            _employees = new PagedListView<Employee>(MovePage) {PageSize = 10};
            _employees.PropertyChanged += delegate { UpdatePageInfo(); };

            _employees.MoveToFirstPage();
        }

        private void UpdatePageInfo()
        {
            EmployeeCount.Text = string.Format("Total Number of Employees: {0}", _employees.TotalItemCount);
            PageIndex.Text = string.Format("Page {0} of {1}", _employees.PageIndex, _employees.TotalNumberOfPages());
            PageSize.Text = string.Format("Page Size: {0}", _employees.PageSize);

            var count = _employees.Cast<Employee>().Count();
            PageCount.Text = string.Format("Employees on this Page: {0}", count);

            _currentEmployee = _employees.Cast<Employee>().FirstOrDefault();
            UpdateEmployeeInfo();
        }

        private void UpdateEmployeeInfo()
        {
            if (_currentEmployee == null)
            {
                Employee.Text = string.Empty;
                EmployeeIdentifier.Text = string.Empty;
                EmployeeFirstName.Text = string.Empty;
                EmployeeLastName.Text = string.Empty;
                EmployeeJobTitle.Text = string.Empty;
                EmployeeTelephone.Text = string.Empty;

                return;
            }

            var i1 = _employees.Cast<Employee>().ToList().IndexOf(_currentEmployee);
            var index = (_employees.PageSize * _employees.PageIndex + i1) + 1;

            Employee.Text = string.Format("Employee {0} of {1}", index, _employees.TotalItemCount);
            EmployeeIdentifier.Text = string.Format("Identifier: {0}", _currentEmployee.Identifier);
            EmployeeFirstName.Text = string.Format("First Name: {0}", _currentEmployee.FirstName);
            EmployeeLastName.Text = string.Format("Last Name: {0}", _currentEmployee.LastName);
            EmployeeJobTitle.Text = string.Format("Job Title: {0}", _currentEmployee.JobTitle);
            EmployeeTelephone.Text = string.Format("Telephone: {0}", _currentEmployee.Telephone);
        }
        
        private void NextEmployeeClick(object sender, RoutedEventArgs e)
        {
            var count = _employees.Cast<Employee>().Count();
            var index = _employees.Cast<Employee>().ToList().IndexOf(_currentEmployee);
            if (index + 1 == count)
                return;

            _currentEmployee = _employees.Cast<Employee>().ToList()[++index];
            UpdateEmployeeInfo();
        }

        private void PreviousEmployeeClick(object sender, RoutedEventArgs e)
        {
            var index = _employees.Cast<Employee>().ToList().IndexOf(_currentEmployee);
            if (index == 0)
                return;

            _currentEmployee = _employees.Cast<Employee>().ToList()[--index];
            UpdateEmployeeInfo();
        }
        
        private void FirstPageClick(object sender, RoutedEventArgs e)
        {
            _employees.MoveToFirstPage();
        }

        private void LastPageClick(object sender, RoutedEventArgs e)
        {
            _employees.MoveToLastPage();
        }

        private void NextPageClick(object sender, RoutedEventArgs e)
        {
            _employees.MoveToNextPage();
        }

        private void PreviousPageClick(object sender, RoutedEventArgs e)
        {
            _employees.MoveToPreviousPage();
        }

        private IObservable<PagedList<Employee>> MovePage(int pageIndex, int pageSize)
        {
            // This is where the work is done, in this example i'm just filtering a predefined
            // list, you could be calling a backend server with the pagination values - index & size...

            var skip = (pageIndex) * pageSize;
            if (skip < 0)
            {
                skip = 0;
                pageIndex = 0;
            }

            if (pageSize < 0)
                pageSize = 100;

            var pagedList = new PagedList<Employee>
                                {
                                    Total = _allEmployees.Count,
                                    PageIndex = pageIndex,
                                    PageSize = pageSize,
                                    Items = _allEmployees.Skip(skip).Take(pageSize).ToList()
                                };

            return Observable.Return(pagedList);
        }

        private static IList<Employee> CreateEmployees(int number)
        {
            var employees = new List<Employee>();

            for (var j = 0; j < number; j++)
            {
                var employee = new Employee
                                   {
                                       Identifier = Guid.NewGuid(),
                                       FirstName = TestHelper.CreateString(TestHelper.CreateNumber(3, 9), true)
                                   };

                if (TestHelper.CreateNumber(0, 7) % 2 == 0)
                    employee.LastName = TestHelper.CreateString(TestHelper.CreateNumber(3, 9), true);
                else
                    employee.LastName = string.Format("{0}-{1}", TestHelper.CreateString(TestHelper.CreateNumber(3, 9), true),
                                                      TestHelper.CreateString(TestHelper.CreateNumber(2, 12), false));

                var sb = new StringBuilder();
                var parts = TestHelper.CreateNumber(1, 6);
                for (var i = 0; i < parts; i++)
                    sb.AppendFormat("{0} ", TestHelper.CreateString(TestHelper.CreateNumber(3, 7), true));

                employee.JobTitle = sb.ToString().Trim();

                employee.Telephone = string.Format("+44 203 {0}{1}{2} {3}{4}{5}{6}", TestHelper.CreateNumber(1, 9),
                                                         TestHelper.CreateNumber(0, 9),
                                                         TestHelper.CreateNumber(0, 9),
                                                         TestHelper.CreateNumber(1, 9),
                                                         TestHelper.CreateNumber(0, 9),
                                                         TestHelper.CreateNumber(0, 9),
                                                         TestHelper.CreateNumber(0, 9));

                employees.Add(employee);
            }

            return employees;
        }
    }
}